Skip to content

[pull] main from MetaMask:main#342

Merged
pull[bot] merged 18 commits into
Reality2byte:mainfrom
MetaMask:main
Nov 20, 2025
Merged

[pull] main from MetaMask:main#342
pull[bot] merged 18 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Nov 20, 2025

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

christopherferreira9 and others added 18 commits November 20, 2025 11:36
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Updates E2E docs to make Expo prebuilds iOS-only and removes Android
prebuild instructions.
> 
> - **Docs** (`docs/readme/e2e-testing.md`):
>   - Rename section to “Use Expo prebuilds (iOS Only)”.
> - Remove Android prebuild instructions (APK/test APK steps, emulator
launch), retaining iOS prebuild guidance only.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e6adac0. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…criptionService cp-7.60.0 (#22983)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR fixes a missing `returnOnEquity` calculation in the
`HyperLiquidSubscriptionService.aggregateAccountStates()` method.


## **Changelog**

CHANGELOG entry: Fixed a bug where the PnL % would not show 


## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2086

## **Manual testing steps**

```gherkin
Feature: Return on Equity calculation in Perps account aggregation

  Scenario: user views account state with open HIP3 positions
    Given user has open perpetual positions with unrealized PnL
    
    Then the returnOnEquity field should be correctly calculated as (unrealizedPnl / marginUsed) * 100
    And the value should be formatted to one decimal place

```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

![IMG_954DF8480A63-1](https://github.com/user-attachments/assets/166b53a5-5afd-4f24-9424-d9d9fef269a6)


### **After**

<!-- [screenshots/recordings] -->
<img width="1170" height="2532" alt="Simulator Screenshot - iPhone 16e -
2025-11-20 at 09 47 15"
src="https://github.com/user-attachments/assets/435d4952-8b54-4c4e-ae30-c7b8a11bcd36"
/>


## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Computes `returnOnEquity` in
`HyperLiquidSubscriptionService.aggregateAccountStates` and adds unit
tests covering multiple scenarios and rounding.
> 
> - **Service**:
> - Compute `returnOnEquity` in
`HyperLiquidSubscriptionService.aggregateAccountStates` as
`((totalUnrealizedPnl / totalMarginUsed) * 100).toFixed(1)` and include
it in the aggregated `AccountState`.
> - **Tests**:
> - Add ROE test suite in `HyperLiquidSubscriptionService.test.ts`
validating positive, negative, zero-margin, mixed PnL, large gains, and
one-decimal rounding; mock adapter accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
316fc46. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

PR to add the new trending tokens page.
It also makes it possible to click on any trending token and it should
navigate to the token details page.


## **Changelog**

CHANGELOG entry: Added a new page for trending tokens with sort
functionalities.

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->



https://github.com/user-attachments/assets/c98da828-a2f8-4229-b37a-4ec68fc5146e


## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Add a full “Trending Tokens” view with sorting/filtering and
navigation, plus supporting hooks, utilities, and updates across asset
views and network tooling.
> 
> - **Trending Tokens (UI)**:
> - New full view `TrendingTokensFullView` with list
(`TrendingTokensList`) and row item (`TrendingTokenRowItem`) components,
token logos/badges, and skeletons.
> - Bottom sheets for time, network, and sort
(`TrendingTokenTimeBottomSheet`, `TrendingTokenNetworkBottomSheet`,
`TrendingTokenPriceChangeBottomSheet`).
> - **Navigation**:
> - Register `TrendingTokensFullView` in `MainNavigator` with slide-in
animation; add route `Routes.WALLET.TRENDING_TOKENS_FULL_VIEW`.
> - **Data & Hooks**:
> - New `useTrendingRequest` hook (with debounce + in‑memory TTL cache)
and utilities (`sortTrendingTokens`, `getTrendingTokenImageUrl`).
>   - New `usePopularNetworks` hook for network selection.
> - **Asset Views**:
> - `AssetOverview`: compute fiat from balance/price when missing;
refine balance derivation; handle native/non‑EVM; expose
`pricePercentChange1d`.
>   - `TokenDetails`: show details when address/decimals present.
> - `AssetDetails`: support assets opened from trending/search (build
token object when not in portfolio; hide empty aggregators).
> - `AssetOptions`: only show “Remove token” if present; checksum
address; CAIP handling.
> - **Network Modal**:
>   - Add `skipEnableNetwork` prop to avoid auto‑enable during add flow.
> - **Utilities**:
> - `getTokenDetails` fallback to `asset.decimals`; historical prices
handle 204.
>   - Etherscan/BSC: add BSC constants and base URL handling.
> - **i18n**:
>   - Add `trending.*` strings.
> - **Tests**:
> - Extensive unit tests for new components/hooks and updated logic;
snapshot updates/removals.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fe65371. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

TRON staked tokens were visible in the send flow. This PR modifies some
selectors so that we filter out TRON staked tokens.

## **Changelog**

CHANGELOG entry: fix: filter out TRON staked tokens

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-1814

## **Manual testing steps**

1. Go to send flow
2. Filter TRON
3. EXPECTED: TRON staked tokens are not visible

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<img width="316" height="720" alt="image"
src="https://github.com/user-attachments/assets/d8a4656b-cf62-49e8-b6c9-1cadfb3eab4d"
/>

### **After**

https://www.loom.com/share/e5ca32a5434e46ab907d8832ab3af239

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Exclude Tron staked bandwidth/energy assets from token lists by
introducing a filtered assets selector, wiring it into the send tokens
hook and sorting selector, with accompanying tests.
> 
> - **Selectors**:
> - Add `selectFilteredAssetsBySelectedAccountGroup` to remove Tron
resource symbols (`ENERGY`, `BANDWIDTH`, and staked variants) across
`TrxScope` networks.
> - Update `selectSortedAssetsBySelectedAccountGroup` to consume the
filtered selector.
> - **Hooks**:
> - `useAccountTokens` now uses
`selectFilteredAssetsBySelectedAccountGroup` to exclude Tron
staked/resource tokens in the send flow.
> - **Tests**:
> - Add coverage for `selectFilteredAssetsBySelectedAccountGroup` Tron
filtering.
>   - Update `useAccountTokens` tests to use the new selector.
>   - Minor assertion tweak to `toStrictEqual` for assets shape.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8f9af0e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This change makes it so that the perps flow follows the same approach as
predict/swaps so that we show points estimations when a user has opted
into the rewards program. If the active account isn't enrolled, but the
user has opted into the program with another account, then they'll have
the option to enroll their account while they're opening/closing
positions.

## **Changelog**

CHANGELOG entry: allow enroll rewards account in perps flow

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/RWDS-800

## **Screenshots/Recordings**

### **After**

Allowing users to enroll the active account if we detect that another
account is tied to a rewards subscription, but the active account isn't.
(Only if we support these accounts)

<img width="680" height="433" alt="Screenshot-2025-11-18-16:10:34"
src="https://github.com/user-attachments/assets/29a6bc55-4e81-4057-9cd5-7a28d3371319"
/>

---

Examples of an enrolled account still showing points estimates like
before:

<img width="695" height="469" alt="Screenshot-2025-11-18-16:12:02"
src="https://github.com/user-attachments/assets/8e8c84a1-73f8-42af-8e37-b2b3c4eb2dfc"
/>

<img width="490" height="972" alt="Screenshot-97"
src="https://github.com/user-attachments/assets/2e566d09-9cec-4d56-9a1f-32fe7db66778"
/>

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Gate Perps/Predict points behind rewards opt‑in, show inline
enrollment when supported, and add Predict points estimation with
controller types; update UI and tests accordingly.
> 
> - **Perps UI**
> - Gate rewards row by `accountOptedIn`; pass `accountOptedIn` and
`rewardsAccount` through `PerpsOrderView`, `PerpsClosePositionView`, and
`PerpsCloseAllPositionsView` into `PerpsCloseSummary`.
> - Render `RewardsAnimations` when opted in, otherwise show
`AddRewardsAccount` if an eligible account exists.
> - **Hooks**
> - New `usePerpsRewardAccountOptedIn(trigger?)` to check rewards
feature, subscription, CAIP account, and opt‑in support; subscribes to
`RewardsController:accountLinked`.
> - Update `usePerpsRewards` to consume opt‑in state and expose
`accountOptedIn`/`account`; only show points when amount valid and
opt‑in check not null.
> - **Predict**
> - Add `usePredictRewards(totalFeeUsd?)` to check opt‑in and estimate
points; wire into `PredictBuyPreview` and `PredictFeeSummary` with
`shouldShowRewardsRow`, `accountOptedIn`, loading/error states, and
`AddRewardsAccount` fallback.
> - **Rewards Animation**
> - Only show error info icon when `infoOnPress` is provided; support
hidden value display.
> - **Controller Types**
> - Extend rewards types: add `EstimatePredictContextDto`,
`predictContext` to `EstimatePointsContextDto`, include `PREDICT` in
`PointsEventEarnType`.
> - **Tests**
> - Extensive updates/coverage for new opt‑in logic, UI branching,
hooks, and Predict points estimation.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b0fe230. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This fixes an issue where the flask e2e artifact name was the same as
the regular smoke tests on android and preventing the second one to
upload.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:null
## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Renames the uploaded artifact in
`.github/workflows/run-e2e-smoke-tests-android-flask.yml` to
`e2e-smoke-android-flask-all-test-artifacts`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f5db6b5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ller versions (#23029)

## **Description**

Update controller versions for `@metamask/transaction-controller` and
`@metamask/transaction-pay-controller`.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

## **Manual testing steps**

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Upgrade `@metamask/transaction-controller` to `62.0.0` and
`@metamask/transaction-pay-controller` to `^9.0.0`, aligning related
dependencies and peer ranges.
> 
> - **Dependencies**:
> - Bump `@metamask/transaction-controller` from `61.3.0` to `62.0.0`
(update `resolutions` and patched reference in
`package.json`/`yarn.lock`).
> - Bump `@metamask/transaction-pay-controller` from `^7.0.0` to
`^9.0.0`.
>   - Align transitive deps/peers in `yarn.lock`:
>     - `@metamask/controller-utils` to `^11.16.0`.
> - Update peer ranges for `@metamask/accounts-controller`,
`@metamask/gas-fee-controller`, `@metamask/network-controller`, and
related bridge/assets controllers.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1dfd594. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

The purpose of this PR is to require a build number in the Mobile bug
report template.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a required Build number field to the bug report template and
clarifies the Version field description.
> 
> - **GitHub Issue Template**:
>   - **Bug report** (`.github/ISSUE_TEMPLATE/bug-report.yml`):
>     - Add required `Build number` input field.
> - Update `Version` field description to reference "About MetaMask".
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d4d4020. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This bumps Snaps packages to the latest version. Notable changes
include:

- Ensure the user has onboarded before allowing usage of Snaps.
- Use a mutex for `snap_setState` operations
- Support specified `clientVersions` in the registry

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Fixed a rare issue where Snaps updating state rapidly
would lose data

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Updates Snaps deps and integrates onboarding gating in
`SnapController`, adds mobile client config to Snaps registry, exposes
`runSaga`, and makes wallet account discovery non-blocking.
> 
> - **Snaps**:
> - **Dependencies**: Bump `@metamask/snaps-controllers` to `^17.0.0`
and `@metamask/snaps-rpc-methods` to `^14.1.1` (lockfile updated).
> - **Controller Init
(`app/core/Engine/controllers/snaps/snap-controller-init.ts`)**:
> - Add `ensureOnboardingComplete` using `redux-saga` to block Snap
usage until onboarding completes.
> - Wire into `SnapController` options; add tests for behavior and
metrics/event plumbing.
> - **Registry Init
(`app/core/Engine/controllers/snaps/snaps-registry-init.ts`)**:
> - Pass `clientConfig` with `{ type: 'mobile', version: getVersion()
}`; add tests with mocked version.
> - **Store (`app/store/index.ts`)**:
> - Export `runSaga` for external saga execution (used by onboarding
gate); update tests/mocks accordingly.
> - **Authentication (`app/core/Authentication/Authentication.ts`)**:
> - Make initial account discovery during wallet creation/restore
non-blocking (`Promise.all(...).catch(console.error)`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
66c9921. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…22844)

## **Description**

This PR implements a **complete service layer architecture** for the
PerpsController by extracting business logic into 8 specialized,
composable services. This refactoring dramatically improves code
maintainability, testability, and separation of concerns while
maintaining **100% backward compatibility**.

### Why this refactoring?

The PerpsController had grown to **2,454 lines**, making it difficult to
maintain, test, and reason about. Business logic was deeply embedded in
the controller, mixing concerns like:
- HIP-3 and feature flag configuration
- Account state management and withdrawals
- Market data fetching and caching
- Eligibility and geo-blocking
- Rewards integration
- Trading operations
- Deposit flow orchestration
- Data lake reporting

### What changed?

**8 New Services Created:**

1. **FeatureFlagConfigurationService** (336 lines)
   - Remote HIP-3 configuration validation
   - Geo-blocking configuration management
   - "Sticky remote" pattern enforcement

2. **AccountService** (343 lines)
   - Withdrawal orchestration and validation
   - Account state management
   - Asset eligibility checks

3. **MarketDataService** (192 lines)
   - Position, order, and market data fetching
   - Standardized error handling and tracing
   - State update coordination

4. **EligibilityService** (44 lines)
   - Geo-location fetching with 5-minute cache
   - Region-based eligibility checks
   - Concurrent request deduplication

5. **RewardsIntegrationService** (23 lines)
   - Fee discount calculation from RewardsController
   - CAIP account ID formatting
   - Network/chain ID resolution

6. **TradingService** (800+ lines)
   - Order placement, cancellation, editing
   - Position management (open/close/TPSL)
   - Fee discount application and cleanup

7. **DepositService** (300+ lines)
   - Cross-chain deposit transaction preparation
   - CAIP asset parsing and validation
   - Bridge contract integration

8. **DataLakeService** (329 lines)
   - Order event reporting to analytics
   - Authentication token management
   - Network-aware endpoint selection

**Comprehensive Test Coverage:**
- Created test files for all 8 services
- Tests cover success paths, error handling, and edge cases
- All TypeScript errors resolved in test files
- Cleaned up PerpsController.test.ts (removed 203 lines of redundant
tests)

**ServiceContext Interface:**
- Centralized dependency injection for all services
- Includes: tracing, analytics, state management, error context
- Enables testing services in isolation with mock contexts

**Controller Simplification:**
- Methods became thin delegations (~10-15 lines each):
  1. Create ServiceContext with required callbacks
  2. Call service method
  3. Handle any errors locally
- PerpsController: 2,454 → 1,461 lines after test cleanup

### Architecture Pattern: Delegation + Composition

This establishes a **composable service architecture**:

```typescript
// Controller: Thin delegation layer
async getPositions() {
  this.ensureInitialized();
  const context = this.createServiceContext('getPositions');
  return MarketDataService.getPositions({
    provider: this.getActiveProvider(),
    context,
  });
}
```

```typescript
// Service: Fat orchestration layer
static async getPositions({ provider, context }) {
  const traceId = trace({ name: 'Perps Get Positions', ...context.tracingContext });

  try {
    const positions = await provider.getPositions();
    context.stateManager?.update(draft => {
      draft.lastUpdateTimestamp = Date.now();
    });
    endTrace({ traceId, success: true });
    return positions;
  } catch (error) {
    endTrace({ traceId, success: false, error });
    throw error;
  }
}
```

**Key Benefits:**
- ✅ **Single Responsibility**: Each service handles one domain
- ✅ **Testability**: Services tested independently with comprehensive
test suites
- ✅ **Composability**: Services can be composed/reused across features
- ✅ **Maintainability**: Small, focused files vs. 2,454-line controller
- ✅ **Type Safety**: All TypeScript errors resolved
- ✅ **Zero Breaking Changes**: 100% backward compatible

### Line Count Changes

**Removed:**
- PerpsController.test.ts: -203 lines (redundant tests)
- PerpsController.ts: -198 lines (extracted to services)

**Added:**
- FeatureFlagConfigurationService.ts: +336 lines
- AccountService.ts: +343 lines
- MarketDataService.ts: +192 lines
- TradingService.ts: +800 lines
- DepositService.ts: +300 lines
- DataLakeService.ts: +329 lines
- EligibilityService.ts: +44 lines
- RewardsIntegrationService.ts: +23 lines
- **8 test files**: Comprehensive test coverage for all services

**Net Impact:**
- Production code: Better organized into focused modules
- Test coverage: Significantly improved with dedicated test suites
- Controller complexity: Reduced by ~40%

### Future Work

This refactoring establishes patterns for:
- [ ] Breaking down HyperLiquidProvider (2,000+ lines)
- [ ] Extracting subscription management service
- [ ] Creating protocol-agnostic provider interface
- [ ] Additional service extractions as needed

### Verification

- [x] All service tests passing
- [x] ESLint validation passed
- [x] TypeScript validation passed
- [x] Backward compatibility verified (100%)
- [x] PerpsController tests still passing

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Part of ongoing Perps controller architecture improvements to reduce
complexity and improve maintainability through service decomposition.

## **Manual testing steps**

This is a **pure refactoring** with comprehensive test coverage. All
existing Perps functionality works identically:

```gherkin
Feature: Service-Based Architecture

  Scenario: Position and account data fetching
    Given user has active positions
    When MarketDataService.getPositions() is called
    Then positions are returned with proper tracing
    And state is updated with timestamps

  Scenario: Withdrawal validation and execution
    Given user requests withdrawal
    When AccountService.withdraw() is called
    Then validation checks pass/fail correctly
    And state updates match previous behavior

  Scenario: Fee discount calculation
    Given user has rewards tier with discount
    When RewardsIntegrationService.calculateUserFeeDiscount() is called
    Then correct discount bips are returned
    And CAIP account formatting works correctly
```

**Testing Notes:**
- Comprehensive automated tests cover all service logic
- No new manual testing required beyond existing Perps tests
- All existing behaviors preserved and verified by tests

## **Screenshots/Recordings**

N/A - Pure refactoring with comprehensive test coverage

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests (comprehensive test suites for all services)
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria and
includes necessary testing evidence.

---

## **Technical Details**

### Services Architecture

Each service follows the same pattern:

```typescript
// 1. Static methods (no instance state)
export class ServiceName {
  static async operation({
    provider,      // Provider dependency
    context,       // ServiceContext with callbacks
    ...params      // Operation-specific parameters
  }) {
    // 2. Tracing
    const traceId = trace({ name: 'Operation Name', ...context.tracingContext });

    try {
      // 3. Business logic
      const result = await provider.someMethod(params);

      // 4. State updates via callback
      context.stateManager?.update(draft => {
        draft.lastUpdate = Date.now();
      });

      // 5. Analytics
      context.analytics?.trackEvent('operation_complete', { result });

      // 6. Tracing completion
      endTrace({ traceId, success: true, data: result });

      return result;
    } catch (error) {
      // 7. Error handling
      Logger.error(error, context.errorContext);
      endTrace({ traceId, success: false, error: error.message });
      throw error;
    }
  }
}
```

### Files Changed

**Created (8 services):**
-
`app/components/UI/Perps/controllers/services/FeatureFlagConfigurationService.ts`
- `app/components/UI/Perps/controllers/services/AccountService.ts`
- `app/components/UI/Perps/controllers/services/MarketDataService.ts`
- `app/components/UI/Perps/controllers/services/EligibilityService.ts`
-
`app/components/UI/Perps/controllers/services/RewardsIntegrationService.ts`
- `app/components/UI/Perps/controllers/services/TradingService.ts`
- `app/components/UI/Perps/controllers/services/DepositService.ts`
- `app/components/UI/Perps/controllers/services/DataLakeService.ts`

**Created (8 test files):**
- All corresponding `.test.ts` files with comprehensive test coverage

**Modified:**
- `app/components/UI/Perps/controllers/services/ServiceContext.ts`
(expanded interface)
- `app/components/UI/Perps/controllers/PerpsController.ts` (delegations
to services)
- `app/components/UI/Perps/controllers/PerpsController.test.ts` (cleaned
up redundant tests)

### Composability Benefits

**Before:**
```typescript
// Monolithic controller - 2,454 lines
class PerpsController {
  async withdraw(params) {
    // 50 lines of validation logic
    // 30 lines of state management
    // 20 lines of provider calls
    // 10 lines of error handling
    // Total: 110 lines, hard to test
  }
}
```

**After:**
```typescript
// Thin controller - delegates to service
class PerpsController {
  async withdraw(params) {
    this.ensureInitialized();
    return AccountService.withdraw({
      provider: this.getActiveProvider(),
      params,
      context: this.createServiceContext('withdraw'),
    });
  }
}

// Composable service - can be reused, tested independently
class AccountService {
  static async withdraw({ provider, params, context }) {
    // Full orchestration logic in isolated, testable module
    // Comprehensive unit tests covering all edge cases
  }
}
```

**Reusability Example:**
```typescript
// Services can be composed across features
async executeWithdrawal(params) {
  // Step 1: Check eligibility
  const isEligible = await EligibilityService.checkEligibility(['US']);

  // Step 2: Calculate fee discount
  const discount = await RewardsIntegrationService.calculateUserFeeDiscount({
    rewardsController: this.rewardsController,
    networkController: this.networkController,
    messenger: this.messagingSystem,
  });

  // Step 3: Execute withdrawal
  return AccountService.withdraw({ provider, params, context });
}
```

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Extracts Perps logic into dedicated services and rewires
PerpsController to thin delegations, adding comprehensive tests and
minor state/schema tweaks.
> 
> - **Architecture**:
> - **Controller Delegation**: `PerpsController` now delegates to
services (`TradingService`, `MarketDataService`, `AccountService`,
`DepositService`, `DataLakeService`, `EligibilityService`,
`RewardsIntegrationService`, `FeatureFlagConfigurationService`).
> - **ServiceContext**: Introduces DI context (`tracing`, `analytics`,
`stateManager`, `messenger`, etc.) for services.
> - **Features/Behavior**:
> - **Deposits**: New `depositWithConfirmation` via `DepositService` and
`TransactionController` flow.
> - **Eligibility & HIP-3**: Remote flag handling and geo-block checks
moved to services; sticky-remote logic preserved.
> - **Trading**: Order/place/edit/cancel, batch cancel/close, TPSL
updates with fee discounts and analytics via `TradingService`.
> - **Data Lake**: Order reporting extracted with retries and auth
handling.
> - **Market Data**: Positions, orders, funding, markets, candles, fees,
routes abstracted to `MarketDataService`.
> - **State/Schema**:
>   - Removes `pendingOrders` from state and related snapshots.
> - **Tests**:
> - Adds comprehensive unit tests for all services and updates
controller tests/mocks.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f221ff4. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

The id was invalid which was breaking the bug report template.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Rename field id from `build number` to `build-number` in
`.github/ISSUE_TEMPLATE/bug-report.yml`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a10167c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Hardcode `isRemoveGlobalNetworkSelectorEnabled` feature flag 

## **Changelog**

CHANGELOG entry:null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

`~`

### **Before**

`~`

### **After**

`~`

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Hardcodes `isRemoveGlobalNetworkSelectorEnabled` to always return
`true`, removing the environment flag check.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
229cac5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Remove unnecessary component mocks and improve test maintainability
across
11 Predict test files. Tests now use real components from design system
instead of mocked implementations.

Changes:
- Remove @metamask/design-system-react-native component mocks
- Remove Text, Button, Icon, SafeAreaView component mocks
- Remove theme utility mocks
- Consolidate redundant tests
- Apply AAA pattern (Arrange, Act, Assert) consistently
- Use action-oriented test names without "should"
- Add minimal testID-only mocks where needed for assertions

Files refactored:
- PredictBuyPreview.test.tsx: 2454 → 705 lines (71% reduction)
- PredictActivity.test.tsx: 280 → 135 lines (52% reduction)
- PredictActivityDetail.test.tsx: 1020 → 392 lines (62% reduction)
- PredictAddFundsSheet.test.tsx: 542 → 154 lines (72% reduction)
- PredictMarketList.test.tsx: 410 → 301 lines (27% reduction)
- PredictNewButton.test.tsx: 260 → 97 lines (63% reduction)
- PredictOffline.test.tsx: 236 → 63 lines (73% reduction)
- PredictPositionEmpty.test.tsx: Refactored with improved coverage
- PredictPositionsHeader.test.tsx: 990 → 275 lines (72% reduction)
- PredictUnavailable.test.tsx: 489 → 169 lines (65% reduction)
- PredictMarketDetails.test.tsx: 3377 → 3211 lines (5% reduction)

Results:
- All 300+ tests pass ✅
- Coverage maintained at 85-95% across all components
- Tests are less brittle to design system updates
- Improved test readability and maintainability

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Refactors Predict tests to use real components over mocks,
consolidating and simplifying suites across many files with improved
navigation, formatting, and interaction assertions.
> 
> - **Testing (Predict)**:
> - Replace design-system and UI mocks with real components; adopt
minimal/testID-only mocks where necessary.
> - Consolidate and simplify suites across `PredictActivity`,
`ActivityDetail`, `AddFundsSheet`, `MarketList`, `NewButton`, `Offline`,
`PositionEmpty`, `PositionsHeader`, `Unavailable`, `BuyPreview`,
`SellPreview`, `Feed`, `MarketDetails`, `TabView`, and
`TransactionsView`.
> - Focus tests on behavior: navigation flows, callbacks, search
toggling, pull-to-refresh, rewards, balance/error states, and activity
item transformations.
> - Improve maintainability and readability; reduce boilerplate and
brittle mocks while keeping coverage high.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
718095f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Switches the `needs-e2e-build` workflow runner from
`ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md` to `ubuntu-latest`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d5b69f9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
New OTA updates workflow:
<img width="1550" height="391" alt="Screenshot 2025-11-18 at 2 14 29 PM"
src="https://github.com/user-attachments/assets/d73c5978-ad00-4487-a94c-cf36cfeea044"
/>


<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Added OTA updates workflow 

## **Related issues**

Fixes: [21215](#21215)

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**
I was testing it with on pushing my branch. It was working from checking
fingerprints to deploying EAS updates.
I haven't tested the part where we input PR number and branch name but I
hardcoded these before so they should work with inputs as well. This can
only be tested when this PR is merged into main.
<img width="813" height="378" alt="Screenshot 2025-11-18 at 2 23 41 PM"
src="https://github.com/user-attachments/assets/a12c4f04-c0d3-4ccc-9ef7-a3581bfe8be5"
/>

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a GitHub Actions workflow to publish Expo EAS OTA updates gated
by fingerprint comparison and team approval.
> 
> - **CI / GitHub Actions**:
> - **New workflow** `/.github/workflows/push-eas-update.yml` for Expo
EAS OTA updates:
> - `fingerprint-comparison`: checks out PR and base branch, installs
deps, generates Expo fingerprints, compares, and records summary.
> - `approval`: requires `mobile-platform` team approval for OTA when
fingerprints match.
> - `push-update`: verifies `eas` script and required secrets/vars,
prepares signing key, and publishes `eas update` to the configured
`EXPO_CHANNEL`, adding success/failure summaries.
> - `fingerprint-mismatch`: fails the run if fingerprints differ (native
changes detected).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
bf2fc08. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR adds a "Recent activity" section to the Perps Market Details
view, displaying the 3 most recent trades for the selected market.


## **Changelog**

CHANGELOG entry: Added recent activity section to Perps market details
screen showing the 3 most recent trades


## **Related issues**

Fixes:
https://consensyssoftware.atlassian.net/browse/TAT-1968?atlOrigin=eyJpIjoiODNjZmM2NDUwZGM2NDVmMmE1NmM5MGI5NDJmODBkMGIiLCJwIjoiaiJ9

## **Manual testing steps**

```gherkin
Feature: Recent activity on Perps market details

  Scenario: user views recent trades for a market with activity
    Given user is on the Perps market details screen for ETH
    And user has completed at least one trade for ETH

    When user scrolls to the "Recent activity" section
    Then user sees up to 3 recent trades for ETH market
    And each trade displays the token logo, trade type (e.g., "Opened long"), size, and PnL/fee amount
    And user sees a "See all" button in the header

  Scenario: user navigates to full activity list
    Given user is on the Perps market details screen
    And the "Recent activity" section is visible

    When user taps the "See all" button
    Then user is navigated to the Activity screen with the Trades tab selected
    And user sees the back button to return to market details

  Scenario: user views trade details
    Given user is on the Perps market details screen
    And the "Recent activity" section shows trades

    When user taps on a trade item
    Then user is navigated to the position transaction detail screen
    And user sees full details of the selected trade

  Scenario: user views market with no recent activity
    Given user is on the Perps market details screen for a market
    And user has no trades for this market

    When user scrolls to the "Recent activity" section
    Then user sees "No recent activity" message

  Scenario: user views loading state
    Given user is on the Perps market details screen
    And trades are being fetched

    When the "Recent activity" section is loading
    Then user sees skeleton loading indicators for 3 rows
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**



https://github.com/user-attachments/assets/0c33a281-707e-4d55-b5e2-31ee63f94e1c



## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a "Recent activity" section to Perps Market Details showing up to
3 latest trades with navigation to Activity and trade detail, plus
supporting constants, i18n, and tests.
> 
> - **Perps Market Details UI**:
> - Integrates `PerpsMarketTradesList` into `PerpsMarketDetailsView`,
positioned above the risk disclaimer; moves `PerpsNavigationCard` below
the disclaimer.
> - **New Component**: `components/PerpsMarketTradesList`
> - Fetches order fills via `usePerpsOrderFills`, transforms to
transactions, filters by `symbol`, sorts by `timestamp`, and limits to
`PERPS_CONSTANTS.RECENT_ACTIVITY_LIMIT`.
> - Renders header with title and "See all" (navigates to
`Routes.PERPS.ACTIVITY`), shows skeleton while loading, empty state when
no trades, and navigates to `Routes.PERPS.POSITION_TRANSACTION` on item
press.
> - **Constants**: Adds `PERPS_CONSTANTS.RECENT_ACTIVITY_LIMIT = 3` in
`perpsConfig`.
> - **i18n**: Adds `perps.market.recent_trades` and
`perps.market.no_trades` strings.
> - **Tests**: Comprehensive tests for loading/empty states, rendering,
navigation, hook params, filtering/limiting, edge cases, and FlatList
config in `PerpsMarketTradesList.test.tsx`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2db4a4a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…d control bars (#22574)

## **Description**

This is part of a series of PRs removing the
`MM_REMOVE_GLOBAL_NETWORK_SELECTOR` feature flag.
**Master PR for reference:**
#22067

This PR removes the feature flag from hooks, list components, control
bars, and navigation components. The changes enable Network Manager
behavior by default across all affected components.

#### Key Changes:

**Hooks:**
- `useTransactionConfirm` - Now always calls `tryEnableEvmNetwork` after
transaction confirmation
- `useExistingAddress` - Always filters addresses across all enabled
networks
- `useSelectedAccountMultichainBalances` - Uses
`selectEVMEnabledNetworks` to calculate balances
- `useNetworkSwitch` - Removed feature flag from test mocks

**Control Bars:**
- `BaseControlBar` - Removed feature flag logic, always navigates to
Network Manager
- `TokenListControlBar` - Removed conditional navigation, always shows
enabled networks
- `DeFiPositionsControlBar` - Always navigates to Network Manager
instead of TokenFilter

**List Components:**
- `DeFiPositionsList` - Always uses
`selectDefiPositionsByEnabledNetworks` selector
- `TokenFilterBottomSheet` - Always calls `selectNetwork` for Network
Manager integration

**Navigation:**
- `Navbar` - Removed old `PickerNetwork` component and feature flag
checks
- `ActivityView` - Removed feature flag import and conditional logic
- `Wallet` - Updated to use Network Manager behavior

#### Test Updates:
- Removed all `isRemoveGlobalNetworkSelectorEnabled` feature flag mocks
- Removed obsolete test cases that covered old behavior (flag OFF)
- Updated test descriptions from "when feature flag is enabled/disabled"
to describe actual
behavior
- Fixed duplicate test in `useExistingAddress.test.ts` with stale
feature flag reference

#### Behavior Change:
The default behavior is now equivalent to the feature flag being ON. All
components use Network Manager with `NetworkEnablementController` to
determine enabled networks instead of relying on the feature flag or
legacy network selection logic.

## **Changelog**

CHANGELOG entry: Removed `MM_REMOVE_GLOBAL_NETWORK_SELECTOR` feature
flag from hooks, list
components, control bars, and navigation. Components now use Network
Manager behavior by default.

## **Related issues**

Fixes:  Fixes: https://consensyssoftware.atlassian.net/browse/MUL-1132

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

`~`

### **Before**

`~`

### **After**

`~`

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Removes the MM_REMOVE_GLOBAL_NETWORK_SELECTOR flag and makes Network
Manager the default across hooks, lists, navbars, and activity view,
updating logic, styles, and tests accordingly.
> 
> - **Network Manager as default**:
> - Navigation and UI now always route filter actions to
`NetworkManager` (replaces `TokenFilter` flows).
> - Removed `PickerNetwork` usage and related flag checks in `Navbar`
and `ActivityView`.
> - **Hooks**:
> - `useTransactionConfirm`: always calls `tryEnableEvmNetwork(chainId)`
post-confirm.
> - `useExistingAddress`: always aggregates `AddressBook` across
networks.
> - `useSelectedAccountMultichainBalances`: aggregates via
`selectEVMEnabledNetworks` and always across enabled EVM chains.
>   - `useNetworkSwitch` tests simplified to remove flag logic.
> - **Lists and Filters**:
> - `DeFiPositionsList`: always uses
`selectDefiPositionsByEnabledNetworks` for data.
> - `TokenFilterBottomSheet`: always updates Preferences and calls
`selectNetwork`.
> - **Control Bars**:
> - `BaseControlBar`, `TokenListControlBar`, `DeFiPositionsControlBar`:
remove flag branches; always show enabled networks label and navigate to
`NetworkManager`.
> - **Styles**:
> - Control bar button styles standardized (always bordered, rounded,
padded).
> - **Tests/Snapshots**:
> - Removed flag mocks and obsolete cases; updated expectations to
`NetworkManager` navigation and new labels/styles.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
750c2cd. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
timeout build android apk for e2e 40 minutes

Reference of taking only 19 minutes
https://github.com/MetaMask/metamask-mobile/actions/runs/19541397562/job/55948548693
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds `timeout-minutes: 40` to the `build-android-apks` job in
`.github/workflows/build-android-e2e.yml`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c66917a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Nov 20, 2025
@pull pull Bot added the ⤵️ pull label Nov 20, 2025
@pull pull Bot merged commit 2b1a33a into Reality2byte:main Nov 20, 2025
2 of 10 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.